﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace MusicExplorer.Model
{
    public abstract class Entity
    {
        private static Dictionary<EntityType, Type> m_typeMapping;
        public static Entity New(EntityType type, string id, string name, Repository repository, params string[] parameters)
        {
            try
            {
                if(m_typeMapping == null)
                {
                    m_typeMapping = new Dictionary<EntityType,Type>();
                    var allTypes = typeof(Entity).GetTypeInfo().Assembly.DefinedTypes;
                    foreach(var entityType in Enum.GetValues(typeof(EntityType)).Cast<EntityType>())
                    {
                        m_typeMapping.Add(entityType, allTypes.First(t => t.Name == entityType.ToString()).AsType());
                    }
                }

                if(parameters != null && parameters.Length > 0 && parameters.Count(p => p != null) > 0)
                    return (Entity)Activator.CreateInstance(m_typeMapping[type], id, name, repository, parameters);
                else
                    return (Entity)Activator.CreateInstance(m_typeMapping[type], id, name, repository);
            }
            catch(Exception ex)
            {
                throw new Exception("Cannot instantiate entity", ex);
            }
        }

        //public static T New<T>(string id, string name, Repository repository, params string[] parameters) where T : Entity
        //{
        //    try
        //    {
        //        return (T)Activator.CreateInstance(typeof(T), id, name, repository, parameters);
        //    }
        //    catch(Exception ex)
        //    {
        //        throw new Exception("Cannot instantiate entity", ex);
        //    }
        //}

        private readonly string m_id;
        private readonly string m_name;
        private readonly Repository m_repository;

        internal Entity(string id, string name, Repository repository)
        {
            m_id = id;
            m_name = name;
            m_repository = repository;
        }

        internal Entity(string id, string name, Repository repository, params string[] parameters)
        {
            throw new Exception("Inherited entity needs to implement it's own constructor");
        }

        public abstract EntityType Type { get; }
        public string Id { get { return m_id; } }
        public string Name { get { return m_name; } }
        public Repository Repository { get { return m_repository; } }
        public int Position { get; set; }
    }
}
